VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "oXmlIntegrityMSXML"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

 ' Daisy 2.02 Validator, Daisy 2.02 Regenerator, Bruno
 ' The Daisy Visual Basic Tool Suite
 ' Copyright (C) 2003,2004,2005,2006,2007,2008 Daisy Consortium
 '
 ' This library is free software; you can redistribute it and/or
 ' modify it under the terms of the GNU Lesser General Public
 ' License as published by the Free Software Foundation; either
 ' version 2.1 of the License, or (at your option) any later version.
 '
 ' This library is distributed in the hope that it will be useful,
 ' but WITHOUT ANY WARRANTY; without even the implied warranty of
 ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ' Lesser General Public License for more details.
 '
 ' You should have received a copy of the GNU Lesser General Public
 ' License along with this library; if not, write to the Free Software
 ' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Private Const xml_S As String = "([#x20;] | [#x9;] | [#xD;] | [#xA;])+"

Private Const xml_BaseChar As String = _
  "([#x0041;-#x005A;] | [#x0061;-#x007A;] | [#x00C0;-#x00D6;] | [#x00D8;-#x00F6;] | [#x00F8;-#x00FF;] | [#x0100;-#x0131;] | [#x0134;-#x013E;] | [#x0141;-#x0148;] | [#x014A;-#x017E;] | [#x0180;-#x01C3;] | [#x01CD;-#x01F0;] | [#x01F4;-#x01F5;] | [#x01FA;-#x0217;] | [#x0250;-#x02A8;] | [#x02BB;-#x02C1;] | [#x0386;] | [#x0388;-#x038A;] | [#x038C;] | [#x038E;-#x03A1;] | [#x03A3;-#x03CE;] | [#x03D0;-#x03D6;] | [#x03DA;] | [#x03DC;] | [#x03DE;] | [#x03E0;] | [#x03E2;-#x03F3;] | [#x0401;-#x040C;] | [#x040E;-#x044F;] | [#x0451;-#x045C;] | " & _
  "[#x045E;-#x0481;] | [#x0490;-#x04C4;] | [#x04C7;-#x04C8;] | [#x04CB;-#x04CC;] | [#x04D0;-#x04EB;] | [#x04EE;-#x04F5;] | [#x04F8;-#x04F9;] | [#x0531;-#x0556;] | [#x0559;] | [#x0561;-#x0586;] | [#x05D0;-#x05EA;] | [#x05F0;-#x05F2;] | [#x0621;-#x063A;] | [#x0641;-#x064A;] | [#x0671;-#x06B7;] | [#x06BA;-#x06BE;] | [#x06C0;-#x06CE;] | [#x06D0;-#x06D3;] | [#x06D5;] | [#x06E5;-#x06E6;] | [#x0905;-#x0939;] | [#x093D;] | [#x0958;-#x0961;] | [#x0985;-#x098C;] | [#x098F;-#x0990;] | [#x0993;-#x09A8;] | [#x09AA;-#x09B0;] | [#x09B2;] | " & _
  "[#x09B6;-#x09B9;] | [#x09DC;-#x09DD;] | [#x09DF;-#x09E1;] | [#x09F0;-#x09F1;] | [#x0A05;-#x0A0A;] | [#x0A0F;-#x0A10;] | [#x0A13;-#x0A28;] | [#x0A2A;-#x0A30;] | [#x0A32;-#x0A33;] | [#x0A35;-#x0A36;] | [#x0A38;-#x0A39;] | [#x0A59;-#x0A5C;] | [#x0A5E;] | [#x0A72;-#x0A74;] | [#x0A85;-#x0A8B;] | [#x0A8D;] | [#x0A8F;-#x0A91;] | [#x0A93;-#x0AA8;] | [#x0AAA;-#x0AB0;] | [#x0AB2;-#x0AB3;] | [#x0AB5;-#x0AB9;] | [#x0ABD;] | [#x0AE0;] | [#x0B05;-#x0B0C;] | [#x0B0F;-#x0B10;] | [#x0B13;-#x0B28;] | [#x0B2A;-#x0B30;] | [#x0B32;-#x0B33;] | " & _
  "[#x0B36;-#x0B39;] | [#x0B3D;] | [#x0B5C;-#x0B5D;] | [#x0B5F;-#x0B61;] | [#x0B85;-#x0B8A;] | [#x0B8E;-#x0B90;] | [#x0B92;-#x0B95;] | [#x0B99;-#x0B9A;] | [#x0B9C;] | [#x0B9E;-#x0B9F;] | [#x0BA3;-#x0BA4;] | [#x0BA8;-#x0BAA;] | [#x0BAE;-#x0BB5;] | [#x0BB7;-#x0BB9;] | [#x0C05;-#x0C0C;] | [#x0C0E;-#x0C10;] | [#x0C12;-#x0C28;] | [#x0C2A;-#x0C33;] | [#x0C35;-#x0C39;] | [#x0C60;-#x0C61;] | [#x0C85;-#x0C8C;] | [#x0C8E;-#x0C90;] | [#x0C92;-#x0CA8;] | [#x0CAA;-#x0CB3;] | [#x0CB5;-#x0CB9;] | [#x0CDE;] | [#x0CE0;-#x0CE1;] | " & _
  "[#x0D05;-#x0D0C;] | [#x0D0E;-#x0D10;] | [#x0D12;-#x0D28;] | [#x0D2A;-#x0D39;] | [#x0D60;-#x0D61;] | [#x0E01;-#x0E2E;] | [#x0E30] | [#x0E32;-#x0E33;] | [#x0E40;-#x0E45;] | [#x0E81;-#x0E82;] | [#x0E84] | [#x0E87;-#x0E88;] | [#x0E8A;] | [#x0E8D;] | [#x0E94;-#x0E97;] | [#x0E99;-#x0E9F;] | [#x0EA1;-#x0EA3;] | [#x0EA5;] | [#x0EA7;] | [#x0EAA;-#x0EAB;] | [#x0EAD;-#x0EAE;] | [#x0EB0;] | [#x0EB2;-#x0EB3;] | [#x0EBD;] | [#x0EC0;-#x0EC4;] | [#x0F40;-#x0F47;] | [#x0F49;-#x0F69;] | [#x10A0;-#x10C5;] | [#x10D0;-#x10F6;] | [#x1100;] | " & _
  "[#x1102;-#x1103;] | [#x1105;-#x1107;] | [#x1109;] | [#x110B;-#x110C;] | [#x110E;-#x1112;] | [#x113C;] | [#x113E;] | [#x1140;] | [#x114C;] | [#x114E;] | [#x1150;] | [#x1154;-#x1155;] | [#x1159;] | [#x115F;-#x1161;] | [#x1163;] | [#x1165;] | [#x1167;] | [#x1169;] | [#x116D;-#x116E;] | [#x1172;-#x1173;] | [#x1175;] | [#x119E;] | [#x11A8;] | [#x11AB;] | [#x11AE;-#x11AF;] | [#x11B7;-#x11B8;] | [#x11BA;] | [#x11BC;-#x11C2;] | [#x11EB;] | [#x11F0;] | [#x11F9;] | [#x1E00;-#x1E9B;] | [#x1EA0;-#x1EF9;] | [#x1F00;-#x1F15;] | [#x1F18;-#x1F1D;] | [#x1F20;-#x1F45;] | [#x1F48;-#x1F4D;] | " & _
  "[#x1F50;-#x1F57;] | [#x1F59;] | [#x1F5B;] | [#x1F5D;] | [#x1F5F;-#x1F7D;] | [#x1F80;-#x1FB4;] | [#x1FB6;-#x1FBC;] | [#x1FBE;] | [#x1FC2;-#x1FC4;] | [#x1FC6;-#x1FCC;] | [#x1FD0;-#x1FD3;] | [#x1FD6;-#x1FDB;] | [#x1FE0;-#x1FEC;] | [#x1FF2;-#x1FF4;] | [#x1FF6;-#x1FFC;] | [#x2126;] | [#x212A;-#x212B;] | [#x212E;] | [#x2180;-#x2182;] | [#x3041;-#x3094;] | [#x30A1;-#x30FA;] | [#x3105;-#x312C;] | [#xAC00;-#xD7A3;])"

Private Const xml_Ideographic As String = _
  "([#x4E00;-#x9FA5;] | [#x3007;] | [#x3021;-#x3029;])"

Private Const xml_CombiningChar As String = _
  "([#x0300;-#x0345;] | [#x0360;-#x0361;] | [#x0483;-#x0486;] | [#x0591;-#x05A1;] | [#x05A3;-#x05B9;] | [#x05BB;-#x05BD;] | [#x05BF;] | [#x05C1;-#x05C2;] | [#x05C4;] | [#x064B;-#x0652;] | [#x0670;] | [#x06D6;-#x06DC;] | [#x06DD;-#x06DF;] | [#x06E0;-#x06E4;] | [#x06E7;-#x06E8;] | [#x06EA;-#x06ED;] | [#x0901;-#x0903;] | [#x093C;] | [#x093E;-#x094C;] | [#x094D;] | [#x0951;-#x0954;] | [#x0962;-#x0963;] | [#x0981;-#x0983;] | [#x09BC;] | [#x09BE;] | [#x09BF;] | [#x09C0;-#x09C4;] | [#x09C7;-#x09C8;] | [#x09CB;-#x09CD;] | [#x09D7;] | [#x09E2;-#x09E3;] | " & _
  "[#x0A02;] | [#x0A3C;] | [#x0A3E;] | [#x0A3F;] | [#x0A40;-#x0A42;] | [#x0A47;-#x0A48;] | [#x0A4B;-#x0A4D;] | [#x0A70;-#x0A71;] | [#x0A81;-#x0A83;] | [#x0ABC;] | [#x0ABE;-#x0AC5;] | [#x0AC7;-#x0AC9;] | [#x0ACB;-#x0ACD;] | [#x0B01;-#x0B03;] | [#x0B3C;] | [#x0B3E;-#x0B43;] | [#x0B47;-#x0B48;] | [#x0B4B;-#x0B4D;] | [#x0B56;-#x0B57;] | [#x0B82;-#x0B83;] | [#x0BBE;-#x0BC2;] | [#x0BC6;-#x0BC8;] | [#x0BCA;-#x0BCD;] | [#x0BD7;] | [#x0C01;-#x0C03;] | [#x0C3E;-#x0C44;] | [#x0C46;-#x0C48;] | [#x0C4A;-#x0C4D;] | [#x0C55;-#x0C56;] | [#x0C82;-#x0C83;] | " & _
  "[#x0CBE;-#x0CC4;] | [#x0CC6;-#x0CC8;] | [#x0CCA;-#x0CCD;] | [#x0CD5;-#x0CD6;] | [#x0D02;-#x0D03;] | [#x0D3E;-#x0D43;] | [#x0D46;-#x0D48;] | [#x0D4A;-#x0D4D;] | [#x0D57;] | [#x0E31;] | [#x0E34;-#x0E3A;] | [#x0E47;-#x0E4E;] | [#x0EB1;] | [#x0EB4;-#x0EB9;] | [#x0EBB;-#x0EBC;] | [#x0EC8;-#x0ECD;] | [#x0F18;-#x0F19;] | [#x0F35;] | [#x0F37;] | [#x0F39;] | [#x0F3E;] | [#x0F3F;] | [#x0F71;-#x0F84;] | [#x0F86;-#x0F8B;] | [#x0F90;-#x0F95;] | [#x0F97;] | [#x0F99;-#x0FAD;] | [#x0FB1;-#x0FB7;] | [#x0FB9;] | [#x20D0;-#x20DC;] | [#x20E1;] | [#x302A;-#x302F;] | [#x3099;] | [#x309A;])"

Private Const xml_Digit As String = _
  "([#x0030;-#x0039;] | [#x0660;-#x0669;] | [#x06F0;-#x06F9;] | [#x0966;-#x096F;] | [#x09E6;-#x09EF;] | [#x0A66;-#x0A6F;] | [#x0AE6;-#x0AEF;] | [#x0B66;-#x0B6F;] | [#x0BE7;-#x0BEF;] | [#x0C66;-#x0C6F;] | [#x0CE6;-#x0CEF;] | [#x0D66;-#x0D6F;] | [#x0E50;-#x0E59;] | [#x0ED0;-#x0ED9;] | [#x0F20;-#x0F29])"

Private Const xml_Extender As String = _
  "([#x00B7;] | [#x02D0;] | [#x02D1;] | [#x0387;] | [#x0640;] | [#x0E46;] | [#x0EC6;] | [#x3005;] | [#x3031;-#x3035;] | [#x309D;-#x309E;] | [#x30FC;-#x30FE;])"

Private Const xml_Letter As String = "(" & xml_BaseChar & " | " & _
  xml_Ideographic & ")"

Private Const xml_NameChar As String = "(" & xml_Letter & " | " & xml_Digit & _
  " | '.' | '-' | '_' | ':' | " & xml_CombiningChar & " | " & xml_Extender & ")"

Private Const xml_Name As String = "((" & xml_Letter & " | '_' | ':'), " & _
  xml_NameChar & "*)*"

Private Const xml_SystemLiteral As String = "(('""', [^""]*) | (""'"", [^']*))"

Private Const xml_PubidChar As String = "([#x20;] | [#xD;] | [#xA;] | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%])"

Private Const xml_PubidLiteral As String = "(('""', " & xml_PubidChar & "*, '""') | (""'"", (" & xml_PubidChar & " - ""'"")*, ""'""))"

Private Const xml_ExternalID As String = "(('SYSTEM', " & xml_S & ", " & _
  xml_SystemLiteral & ") | ('PUBLIC', " & xml_S & ", " & xml_PubidLiteral & _
  ", " & xml_S & ", " & xml_SystemLiteral & "))"

' This function verifies that the given file validates to the supplied DTD file
Public Function documentValidatesToGivenDTD(iobjReport As oReport, _
  isAbsPath As String, isDTD As String, ieFileType As enuFileType) As Boolean
  
  documentValidatesToGivenDTD = False
  
  If bolUseOnlineDtds Then isDTD = ""
  
  If fncValidateDocument( _
    iobjReport, isAbsPath, isDTD, "xi.dtdGiven", ieFileType _
    ) Then
        documentValidatesToGivenDTD = True
  Else
    objEvent.subLog ("failure in fncValidateDocument: " & _
        fncGetFileName(isAbsPath) & " " & isDTD)
  End If
End Function

' This function verifies that the given file validates to the supplied DTD file
Public Function documentValidatesToCustomDTD(iobjReport As oReport, _
  isAbsPath As String, isDTD As String, ieFileType As enuFileType) As Boolean
  
  documentValidatesToCustomDTD = False
  
  If fncValidateDocument( _
    iobjReport, isAbsPath, isDTD, "xi.dtdCustom", ieFileType _
    ) Then
        documentValidatesToCustomDTD = True
  Else
    objEvent.subLog ("failure in fncValidateDocument: " & _
        fncGetFileName(isAbsPath) & " " & isDTD)
  End If
    
End Function

' This function validates the given document to the given DTD
Private Function fncValidateDocument(iobjReport As oReport, _
  isAbsPath As String, isDTD As String, isObjectReporting As String, _
  ieFileType As enuFileType) As Boolean
  
  Dim oFSO As Object, oFile As Object, sData As String
  'Dim objDom As New object
  
  'fncInsertTime "oXMLIntegrityMSXML.fncValidateDocument"
  
  Dim objDom As Object
  Set objDom = CreateObject("Msxml2.DOMDocument.4.0")

  Set oFSO = CreateObject("Scripting.FileSystemObject")
  Set oFile = oFSO.opentextfile(isAbsPath)
  sData = oFile.ReadAll
  Set oFile = Nothing
    
  'Debug.Print Mid(sData, 1, 300)
  If Not bolUseOnlineDtds Then
    'REVISIT: if inline dtd extension system identifier does not get replaced here
    fncReplaceDtdStatement sData, isDTD, ieFileType
  End If
  'Debug.Print "----"
  'Debug.Print Mid(sData, 1, 300)
  
  On Error GoTo ErrH
  Set oFSO = CreateObject("Scripting.FileSystemObject")
  Set oFile = oFSO.CreateTextFile(sTempPath & "temporary.dat")
  oFile.Write sData
  oFile.Close
  
  On Error GoTo ErrH2
  objDom.resolveExternals = True
  objDom.validateOnParse = True
  objDom.Load sTempPath & "temporary.dat"
  
  If Not objDom.parseError.errorCode = 0 Then
    iobjReport.fncInsertFailedTest isObjectReporting, _
      isAbsPath, objDom.parseError.Line, objDom.parseError.linepos, _
      objDom.parseError.reason
  End If
  
  fncValidateDocument = True
  On Error GoTo ErrH
  
ErrH2:
  Kill sTempPath & "temporary.dat"
ErrH:
  Set oFile = Nothing
  Set oFSO = Nothing
  Set objDom = Nothing
  
  'fncInsertTime "oXMLIntegrityMSXML.fncValidateDocument"
End Function

' This function removes the 'doctype' statement and sets it to point at a local
' DTD. This is necessary while using MSXML without an internet connection.
Private Function fncReplaceDtdStatement( _
  isData As String, isDTD As String, ieFileType As enuFileType) _
  As Boolean
  
  Dim objDTDRules As New oDTDRuleChecker
  Dim lStart As Long, lEnd As Long, lPosition As Long, lCrLfs As Long
  
  Dim sName As String, sExternalID As String
  
  'fncInsertTime "oXMLIntegrityMSXML.fncReplaceDTDStatement"
  
  lStart = InStr(1, isData, "<!DOCTYPE", vbBinaryCompare)
  If Not lStart = 0 Then
    objDTDRules.sData = isData
    objDTDRules.lDataLength = Len(isData)
    objDTDRules.lBytePos = lStart
  
    If Not objDTDRules.conformsTo2("('<!DOCTYPE', " & xml_S & ")") Then GoTo ErrorH
  
    lPosition = objDTDRules.lBytePos
  
    If Not objDTDRules.conformsTo2(xml_Name) Then GoTo ErrorH
    lEnd = objDTDRules.lBytePos
    sName = Mid$(objDTDRules.sData, lPosition, lEnd - lPosition)
  
    If Not objDTDRules.conformsTo2("(" & xml_S & ", " & xml_ExternalID & ")?") Then _
      GoTo ErrorH
   
'ke20030531
    If Not objDTDRules.conformsTo2("(" & xml_S & ")?") Then GoTo ErrorH
  
    If Not objDTDRules.conformsTo2("('[', [^#x005D;]*, (" & xml_S & ")?)?") Then _
      GoTo ErrorH
'ke20030531
    If Not objDTDRules.conformsTo2("(" & xml_S & ")?") Then GoTo ErrorH
  
    If Not objDTDRules.conformsTo2("'>'") Then GoTo ErrorH
    lEnd = objDTDRules.lBytePos
    
    For lPosition = lStart To lEnd
      If Mid$(isData, lPosition, 2) = vbCrLf Then lCrLfs = lCrLfs + 1
    Next lPosition
  Else
    Select Case ieFileType
      Case smil, mastersmil
        sName = "smil"
      Case ncc, discinfo, smilMediaObText, nccmultivolume
        sName = "html"
    End Select
  End If
  
  Dim sDoctype As String, sTempData As String
  
  sDoctype = "<!DOCTYPE " & sName & " SYSTEM 'file:///" & _
    Replace(sDtdPath, "\", "/") & isDTD & "'>"
    
  For lPosition = 2 To lCrLfs
    sDoctype = sDoctype & vbCrLf
  Next lPosition
  
  If lStart > 0 Then
    sTempData = Left$(isData, lStart - 1)
  End If
  
  sTempData = sTempData & sDoctype

  If Len(isData) - lEnd > 0 Then
    isData = sTempData & Right$(isData, Len(isData) - lEnd)
  Else
    isData = sTempData & isData
  End If
  
ErrorH:
  'fncInsertTime "oXMLIntegrityMSXML.fncReplaceDTDStatement"
End Function
